#!/usr/bin/python3
# -*- coding: utf-8; tab-width: 4; indent-tabs-mode: t -*-

import os
import pathlib
import subprocess
from gbs_util import GbsUtil
from gbs_util import TempChdir


class TelnetService:

    def __init__(self, param, uuid, srcIp, srcCert, rootDir):
        self.param = param
        self.uuid = uuid
        self.srcIp = srcIp
        self.srcCert = srcCert
        self.rootDir = rootDir

        self.telnetInitExeFile = os.path.join(self.param.tmpDir, uuid + "-init")

        self.stunnelClientCertFile = os.path.join(self.param.tmpDir, uuid + "-cert.pem")
        self.stunnelCfgFile = os.path.join(self.param.tmpDir, uuid + "-stunnel.conf")
        self.stunnelRndFile = os.path.join(self.param.tmpDir, uuid + "-stunnel.rnd")
        self.stunnelLogFile = os.path.join(self.param.logDir, uuid + "-stunnel.log")

        self.telnetPort = None
        self.stunnelPort = None

        self.telnetProc = None
        self.stunnelProc = None

    def start(self):
        try:
            self.telnetPort = GbsUtil.getFreeTcpPort()
            self.telnetProc = self._runTelnetDaemon()
            GbsUtil.waitTcpPort(self.telnetPort)

            self.stunnelPort = GbsUtil.getFreeTcpPort()
            self.stunnelProc = self._runStunnelDaemon()
            GbsUtil.waitTcpPort(self.stunnelPort)
        except:
            self.stop()
            raise

    def stop(self):
        if self.stunnelProc is not None:
            self.stunnelProc.terminate()
            self.stunnelProc.wait()
        if self.rsyncProc is not None:
            self.rsyncProc.terminate()
            self.rsyncProc.wait()
        GbsUtil.forceDelete(self.stunnelRndFile)
        GbsUtil.forceDelete(self.stunnelCfgFile)
        GbsUtil.forceDelete(self.stunnelClientCertFile)

    def getPort(self):
        return self.stunnelPort

    def _runTelnetDaemon(self):
        buf = ""
        buf += "#!/bin/sh\n"
        buf += "IFS= read -r command\n"
        buf += 'exec sh -c "$command"\n'
        pathlib.Path(self.telnetInitExeFile).write_text(buf)
        os.chmod(self.telnetInitExeFile, 0o755)

        with TempChdir(self.rootDir):
            return subprocess.Popen(["utelnetd", "-l", self.telnetInitExeFile, "-p", str(self.telnetPort)], universal_newlines=True)

    def _runStunnelDaemon(self):
        buf = ""
        buf += "debug = 6\n"
        buf += "output = %s\n" % (self.stunnelLogFile)
        buf += "\n"
        buf += "cert = %s\n" % (self.param.certFile)
        buf += "key = %s\n" % (self.param.privkeyFile)
        buf += "RNDfile = %s\n" % (self.stunnelRndFile)
        buf += "\n"
        buf += "client = no\n"
        buf += "foreground = yes\n"
        buf += "\n"
        buf += "[rsync]\n"
        buf += "accept = 0.0.0.0:%d\n" % (self.stunnelPort)
        buf += "connect = 127.0.0.1:%d\n" % (self.rsyncPort)
        pathlib.Path(self.stunnelCfgFile).write_text(buf)

        cmd = ""
        cmd += "/usr/sbin/stunnel \"%s\" 2>/dev/null" % (self.stunnelCfgFile)
        return subprocess.Popen(cmd, shell=True, universal_newlines=True)
